// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_PENDING_COMPILATION_ERROR_HANDLER_H_
#define V8_PENDING_COMPILATION_ERROR_HANDLER_H_

#include <forward_list>

#include "src/base/macros.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/message-template.h"

namespace v8 {
namespace internal {

    class AstRawString;
    class AstValueFactory;
    class Isolate;
    class Script;

    // Helper class for handling pending compilation errors consistently in various
    // compilation phases.
    class PendingCompilationErrorHandler {
    public:
        PendingCompilationErrorHandler()
            : has_pending_error_(false)
            , stack_overflow_(false)
            , error_type_(kSyntaxError)
        {
        }

        void ReportMessageAt(int start_position, int end_position,
            MessageTemplate message, const char* arg = nullptr,
            ParseErrorType error_type = kSyntaxError);

        void ReportMessageAt(int start_position, int end_position,
            MessageTemplate message, const AstRawString* arg,
            ParseErrorType error_type = kSyntaxError);

        void ReportWarningAt(int start_position, int end_position,
            MessageTemplate message, const char* arg = nullptr);

        bool stack_overflow() const { return stack_overflow_; }

        void set_stack_overflow()
        {
            has_pending_error_ = true;
            stack_overflow_ = true;
        }

        bool has_pending_error() const { return has_pending_error_; }
        bool has_pending_warnings() const { return !warning_messages_.empty(); }

        // Handle errors detected during parsing.
        void ReportErrors(Isolate* isolate, Handle<Script> script,
            AstValueFactory* ast_value_factory);

        // Handle warnings detected during compilation.
        void ReportWarnings(Isolate* isolate, Handle<Script> script);

        V8_EXPORT_PRIVATE Handle<String> FormatErrorMessageForTest(
            Isolate* isolate) const;

        void set_unidentifiable_error()
        {
            has_pending_error_ = true;
            unidentifiable_error_ = true;
        }
        void clear_unidentifiable_error()
        {
            has_pending_error_ = false;
            unidentifiable_error_ = false;
        }
        bool has_error_unidentifiable_by_preparser() const
        {
            return unidentifiable_error_;
        }

    private:
        class MessageDetails {
        public:
            MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(MessageDetails);
            MessageDetails()
                : start_position_(-1)
                , end_position_(-1)
                , message_(MessageTemplate::kNone)
                , arg_(nullptr)
                , char_arg_(nullptr)
            {
            }
            MessageDetails(int start_position, int end_position,
                MessageTemplate message, const AstRawString* arg,
                const char* char_arg)
                : start_position_(start_position)
                , end_position_(end_position)
                , message_(message)
                , arg_(arg)
                , char_arg_(char_arg)
            {
            }

            Handle<String> ArgumentString(Isolate* isolate) const;
            MessageLocation GetLocation(Handle<Script> script) const;
            MessageTemplate message() const { return message_; }

        private:
            int start_position_;
            int end_position_;
            MessageTemplate message_;
            const AstRawString* arg_;
            const char* char_arg_;
        };

        void ThrowPendingError(Isolate* isolate, Handle<Script> script);

        bool has_pending_error_;
        bool stack_overflow_;
        bool unidentifiable_error_ = false;

        MessageDetails error_details_;
        ParseErrorType error_type_;

        std::forward_list<MessageDetails> warning_messages_;

        DISALLOW_COPY_AND_ASSIGN(PendingCompilationErrorHandler);
    };

} // namespace internal
} // namespace v8
#endif // V8_PENDING_COMPILATION_ERROR_HANDLER_H_
